/*
 * Copyright (c) 2009 Tamás Kovács <keccs *at* inbox.com>
 * 
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 * 
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 * 
 */
package keccs.hitTheHay.core;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.prefs.Preferences;

import javax.swing.Timer;

import keccs.hitTheHay.actions.ShutdownAction;
import keccs.hitTheHay.ui.PowerStateChangeAction;


public class ApplicationModel {

	public enum ApplicationState {
		INPUT, COUNTDOWN
	}

	private static final ApplicationModel INSTANCE = new ApplicationModel();
	private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);

	public void addPropertyChangeListener(PropertyChangeListener listener) {
		propertyChangeSupport.addPropertyChangeListener(listener);
	}

	public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {
		propertyChangeSupport.addPropertyChangeListener(propertyName, listener);
	}

	public boolean hasListeners(String propertyName) {
		return propertyChangeSupport.hasListeners(propertyName);
	}

	public void removePropertyChangeListener(PropertyChangeListener listener) {
		propertyChangeSupport.removePropertyChangeListener(listener);
	}

	public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) {
		propertyChangeSupport.removePropertyChangeListener(propertyName, listener);
	}

	private ApplicationState state = ApplicationState.INPUT;
	private PowerStateChangeAction action;
	private int time;
	private long timeLeft;
	// private CountdownThread countdownThread;
	private Preferences preferences = Preferences.userNodeForPackage(getClass());
	private Timer countdownTimer;

	public static ApplicationModel getInstance() {
		return INSTANCE;
	}

	public ApplicationModel() {
		loadPreferences();
	}

	public void setAction(PowerStateChangeAction action) {
		Object old = this.action;
		this.action = action;
		propertyChangeSupport.firePropertyChange("action", old, action); //$NON-NLS-1$
	}

	public PowerStateChangeAction getAction() {
		return action;
	}

	public void setTime(int time) {
		if (state != ApplicationState.INPUT) {
			throw new IllegalStateException("Countdown already started, cannot change time."); //$NON-NLS-1$
		}

		int old = this.time;
		this.time = time;
		propertyChangeSupport.firePropertyChange("time", old, time); //$NON-NLS-1$
	}

	public int getTime() {
		return time;
	}

	void setTimeLeft(long timeLeft) {
		long old = this.timeLeft;
		this.timeLeft = timeLeft;
		propertyChangeSupport.firePropertyChange("timeLeft", old, timeLeft); //$NON-NLS-1$
	}

	public long getTimeLeft() {
		return timeLeft;
	}

	private void setState(ApplicationState state) {
		Object old = this.state;
		this.state = state;
		propertyChangeSupport.firePropertyChange("state", old, state); //$NON-NLS-1$
	}

	public ApplicationState getState() {
		return state;
	}

	public void savePreferences() {
		preferences.put("action", action.getClass().getName()); //$NON-NLS-1$
		preferences.putInt("time", time); //$NON-NLS-1$
	}

	public void loadPreferences() {
		action = new ShutdownAction();
		String actionClassName = preferences.get("action", ""); //$NON-NLS-1$ //$NON-NLS-2$
		try {
			action = (PowerStateChangeAction) Class.forName(actionClassName).newInstance();
		} catch (Exception e) {
			// No problem, just use defaults
		}

		time = preferences.getInt("time", 10); //$NON-NLS-1$
	}

	public void startCountdown() {
		setState(ApplicationState.COUNTDOWN);
		countdownTimer = new Timer(0, new TimeLeftUpdateListener());
		countdownTimer.setDelay(250);
		countdownTimer.start();
	}

	public void stopCountdown() {
		if (countdownTimer != null) {
			countdownTimer.stop();
		}
		setState(ApplicationState.INPUT);
	}
}
